﻿#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>


//操作符

//在vs上，char === signed char
//整型提升
//char类型的取值范围：-128~127
//整型提升讨论的是表达式中char和short类型的值
//int main()
//{
//	/*int a = 10;
//	int b = 10;
//	int c = a + b;*/
//
//	char a = 20;
//	//00000000000000000000000000010100      - 20的补码
//	//00010100                              - char类型只有一个字节8位
//
//	char b = 130;
//	//00000000000000000000000010000010      - 130的补码
//	//10000010 
//
//	char c = a + b;
//	//00000000000000000000000000010100      - a = 20的补码
//	//00000000000000000000000010000010      - b = 130的补码
//	//00000000000000000000000010010110      //截断
//	//10010110                              - c
//	//11111111111111111111111110010110      //整型提升，高位补齐
//	//10000000000000000000000001101001      //补码取反+1
//	//-106                                  //最后结果
//
//	printf("%d\n", c);//-106
//
//	return 0;
//}



//算数转换：
//讨论的是类型大于等于整型的类型的其他类型
//如果某个操作符的各个操作数属于不同的类型，那么除非其中⼀个操作数的转换为另⼀个操作数的类型，否则操作就无法进行。
//int main()
//{
//	int i = 10;
//	i = i-- - --i * (i = -3) * i++ + ++i;
//	printf("i = %d\n", i);
//	return 0;
//}








//指针


//内存的使用和管理
//内存划分为一个个的内存单元，每个内存单元的大小是1个字节
//内存单元的编号 == 地址 == 指针

//int main()
//{
//	int a = 20;//变量创建的本质其实是在内存中申请空间
//	//向内存申请4个字节的空间，用来存放20这个数值
//	//这4个字节，每个字节都有编号（地址）
//	//变量的名字仅仅是给程序员看的，编译器不看，编译器是通过地址找内存单元的
//
//	return 0;
//}


//1.*表示pa是指针变量
//2.int表示pa指向的变量a的类型是int
//int main()
//{
//	int a = 20;
//	//& -- 取地址操作符，拿到变量a的地址
//
//
//	printf("%p\n", &a);
//
//	int* pa = &a;//pa是一个变量，这个变量pa是用来存放地址（指针）的,pa叫指针变量
//	//pa是指针变量的名字，int*是pa的类型
//	
//
//	return 0;
//}



//& -- 取地址
//* -- 解引用（找回）
//int main()
//{
//	int a = 20;
//	int* pa = &a;
//	*pa = 200;//* -- 解引用操作符（间接访问操作符）
//	//a = 200
//	printf("%d\n", a);
//
//	return 0;
//}


//指针变量的大小
//前⾯的内容我们了解到，32位机器假设有32根地址总线，每根地址线出来的电信号转换成数字信号后是1或者0
//那我们把32根地址线产⽣的2进制序列当做⼀个地址，那么⼀个地址就是32个bit位，需要4个字节才能存储。
//如果指针变量是⽤来存放地址的，那么指针变的⼤⼩就得是4个字节的空间才可以。
//同理64位机器，假设有64根地址线，⼀个地址就是64个⼆进制位组成的⼆进制序列，
//存储起来就需要8个字节的空间，指针变量的⼤⼩就是8个字节。

//x86 -- 32位
//x64 -- 64位
//int main()
//{
//	/*int a = 10;
//	int* p = &a;*/
//	//printf("%zd\n", sizeof(p));
//	//1.指针变量是用来存放地址的，地址的存放需要多大空间，那么指针变量的大小就是多大
//	//32位平台下地址是32个bit位（即4个字节） 
//	//64位平台下地址是64个bit位（即8个字节
//
//	char ch = 'w';
//	char* pc = &ch;
//	printf("%zd\n", sizeof(pc));
//
//	
//	return 0;
//}





//• 32位平台下地址是32个bit位，指针变量⼤⼩是4个字节
//• 64位平台下地址是64个bit位，指针变量⼤⼩是8个字节
//• 注意指针变量的⼤⼩和类型是⽆关的，只要指针类型的变量，在相同的平台下，⼤⼩都是相同的。
//int main()
//{
//	printf("%d\n", sizeof(char*));
//	printf("%d\n", sizeof(short*));
//	printf("%d\n", sizeof(int*));
//	printf("%d\n", sizeof(float*));
//	printf("%d\n", sizeof(double*));
//
//	return 0;
//}



//指针类型有什么意思？为什么还




//指针类型的意义
//调试我们可以看到，代码1会将n的4个字节全部改为0，但是代码2只是将n的第⼀个字节改为0。
//结论：指针的类型决定了，对指针解引⽤的时候有多⼤的权限（⼀次能操作⼏个字节）。
//⽐如： char* 的指针解引⽤就只能访问⼀个字节，⽽ int* 的指针的解引⽤就能访问四个字节。

//int main()
//{
//	/*int a = 0x11223344;
//	int* pa = &a;
//	*pa = 0;*/
//
//
//	int a = 0x11223344;
//	char* pa = &a;
//	*pa = 0;
//	
//	return 0;
//}




//指针+-整数
//我们可以看出， char* 类型的指针变量 + 1跳过1个字节， int* 类型的指针变量 + 1跳过了4个字节。
//这就是指针变量的类型差异带来的变化。指针 + 1，其实跳过1个指针指向的元素。指针可以 + 1，那也可以 - 1。
//结论：指针的类型决定了指针向前或者向后⾛⼀步有多⼤（距离）。

//int* pa: pa+1---->+1*sizeof(int)
//         pa+n---->+n*sizeof(int)

//char* pc: pc+1---->1*sizeof(char)
//          pc+n---->n*sizeof(char)
//int main()
//{
//	int a = 20;
//	int* pa = &a;
//	char* pc = &a;
//	printf("&a = %p\n", &a);
//	printf("pa = %p\n", pa);
//	printf("pc = %p\n", pc);
//
//	printf("&a+1 = %p\n", &a+1);
//	printf("pa+1 = %p\n", pa+1);
//	printf("pc+1 = %p\n", pc+1);
//
//	return 0;
//}




//
//void*  指针
//在指针类型中有⼀种特殊的类型是 void* 类型的，可以理解为⽆具体类型的指针（或者叫泛型指针），
//这种类型的指针可以⽤来接受任意类型地址。但是也有局限性， void* 类型的指针不能直接进⾏指针的 + -整数和解引⽤的运算。
//void* 类型的指针可以接收不同类型的地址，但是⽆法直接进⾏指针运算。

//⼀般 void* 类型的指针是使⽤在函数参数的部分，⽤来接收不同类型数据的地址，这样的设计可以实现泛型编程的效果。

int main()
{
	int a = 10;
	/*int* pa = &a;
	char* pc = &a;*/

	char ch = 'w';

	void* pv1 = &a;
	void* pv2 = &ch;

	return 0;
}
